home *** CD-ROM | disk | FTP | other *** search
/ Aminet 24 / Aminet 24 (1998)(GTI - Schatztruhe)[!][Apr 1998].iso / Aminet / comm / mail / Mutt089src.lha / Mutt-0.89i-AMIGA / src / curs_main.c < prev    next >
C/C++ Source or Header  |  1998-01-28  |  31KB  |  1,404 lines

  1. /*
  2.  * Copyright (C) 1996-8 Michael R. Elkins <me@cs.hmc.edu>
  3.  * 
  4.  *     This program is free software; you can redistribute it and/or modify
  5.  *     it under the terms of the GNU General Public License as published by
  6.  *     the Free Software Foundation; either version 2 of the License, or
  7.  *     (at your option) any later version.
  8.  * 
  9.  *     This program is distributed in the hope that it will be useful,
  10.  *     but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  *     GNU General Public License for more details.
  13.  * 
  14.  *     You should have received a copy of the GNU General Public License
  15.  *     along with this program; if not, write to the Free Software
  16.  *     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  */ 
  18.  
  19. #include "mutt.h"
  20. #include "mutt_curses.h"
  21. #include "mutt_menu.h"
  22. #include "mailbox.h"
  23. #include "sort.h"
  24.  
  25. #ifdef _PGPPATH
  26. #include "pgp.h"
  27. #endif
  28.  
  29. #include <ctype.h>
  30. #include <stdlib.h>
  31. #include <unistd.h>
  32. #include <sys/wait.h>
  33. #include <string.h>
  34. #include <sys/stat.h>
  35. #include <errno.h>
  36.  
  37. #define CHECK_MSGCOUNT if (!Context) \
  38.     { \
  39.           mutt_flushinp (); \
  40.         mutt_error ("No mailbox is open."); \
  41.         break; \
  42.     } \
  43.     else if (!Context->msgcount) \
  44.     { \
  45.           mutt_flushinp (); \
  46.         mutt_error ("There are no messages."); \
  47.         break; \
  48.     }
  49.  
  50. #define CHECK_READONLY if (Context->readonly) \
  51.             { \
  52.                   mutt_flushinp (); \
  53.                 mutt_error ("Mailbox is read-only."); \
  54.                 break; \
  55.             }
  56.  
  57. #define CURHDR Context->hdrs[Context->v2r[menu->current]]
  58. #define OLDHDR Context->hdrs[Context->v2r[menu->oldcurrent]]
  59.  
  60. void index_make_entry (char *s, size_t l, MUTTMENU *menu, int num)
  61. {
  62.   int flag = 0;
  63.   HEADER *h = Context->hdrs[Context->v2r[num]];
  64.  
  65.   if ((Sort & SORT_MASK) == SORT_THREADS &&
  66.       Context->msgcount == Context->vcount &&
  67.       h->tree)
  68.   {
  69.     if (h->display_subject)
  70.       flag = M_FORCESUBJ;
  71.     else if (Sort & SORT_REVERSE)
  72.     {
  73.       if ((h->parent->msgno > menu->top + menu->pagelen - 1) && 
  74.       (!h->prev || (h->prev->msgno > menu->top + menu->pagelen - 1)))
  75.     flag = M_FORCESUBJ;
  76.     }
  77.     else if ((h->parent->msgno < menu->top) &&
  78.          (!h->prev || (h->prev->msgno < menu->top)))
  79.       flag = M_FORCESUBJ;
  80.  
  81.     flag |= M_TREE; /* display the thread tree */
  82.   }
  83.  
  84.   _mutt_make_string (s, l, HdrFmt, h, flag);
  85. }
  86.  
  87. static int ci_next_undeleted (int msgno)
  88. {
  89.   int i;
  90.  
  91.   for (i=msgno+1; i < Context->vcount; i++)
  92.     if (! Context->hdrs[Context->v2r[i]]->deleted)
  93.       return (i);
  94.   return (-1);
  95. }
  96.  
  97. static int ci_previous_undeleted (int msgno)
  98. {
  99.   int i;
  100.  
  101.   for (i=msgno-1; i>=0; i--)
  102.     if (! Context->hdrs[Context->v2r[i]]->deleted)
  103.       return (i);
  104.   return (-1);
  105. }
  106.  
  107. /* Return the index of the first new message, or failing that, the first
  108.  * unread message.
  109.  */
  110. static int ci_first_message (void)
  111. {
  112.   int old = -1, i;
  113.  
  114.   if (Context && Context->msgcount)
  115.   {
  116.     for (i=0; i < Context->vcount; i++)
  117.     {
  118.       if (! Context->hdrs[Context->v2r[i]]->read &&
  119.       ! Context->hdrs[Context->v2r[i]]->deleted)
  120.       {
  121.     if (! Context->hdrs[Context->v2r[i]]->old)
  122.       return (i);
  123.     else if (old == -1)
  124.       old = i;
  125.       }
  126.     }
  127.     if (old != -1)
  128.       return (old);
  129.  
  130.     /* If Sort is reverse and not threaded, the latest message is first.
  131.      * If Sort is threaded, the latest message is first iff exactly one
  132.      * of Sort and SortAux are reverse.
  133.      */
  134.     if (((Sort & SORT_REVERSE) && (Sort & SORT_MASK) != SORT_THREADS) ||
  135.     ((Sort & SORT_MASK) == SORT_THREADS &&
  136.      ((Sort ^ SortAux) & SORT_REVERSE)))
  137.       return 0;
  138.     else
  139.       return (Context->vcount ? Context->vcount - 1 : 0);
  140.   }
  141.   return 0;
  142. }
  143.  
  144. /* This should be in mx.c, but it only gets used here. */
  145. static int mx_toggle_write (CONTEXT *ctx)
  146. {
  147.   if (!ctx)
  148.     return -1;
  149.  
  150.   if (ctx->readonly)
  151.   {
  152.     mutt_error ("Cannot toggle write on a readonly mailbox!");
  153.     return -1;
  154.   }
  155.  
  156.   if (ctx->dontwrite)
  157.   {
  158.     ctx->dontwrite = 0;
  159.     mutt_message ("Changes to folder will be written on folder exit.");
  160.   }
  161.   else
  162.   {
  163.     ctx->dontwrite = 1;
  164.     mutt_message ("Changes to folder will not be written.");
  165.   }
  166.  
  167.   return 0;
  168. }
  169.  
  170. /* This function handles the message index window as well as commands returned
  171.  * from the pager (MENU_PAGER).
  172.  */
  173. void mutt_index_menu (void)
  174. {
  175.   char buf[LONG_STRING], helpstr[SHORT_STRING];
  176.   int op = OP_NULL;                 /* function to execute */
  177.   int done = 0;                /* controls when to exit the "event" loop */
  178.   int i = 0, j;
  179.   int tag = 0;                 /* has the tag-prefix command been pressed? */
  180.   int newcount = -1;
  181.   int oldcount = -1;
  182.   int rc = -1;
  183.   MUTTMENU *menu;
  184.   char *cp;                    /* temporary variable. */
  185.   int index_hint;   /* used to restore cursor position */
  186.  
  187.   menu = mutt_new_menu ();
  188.   menu->menu = MENU_MAIN;
  189.   menu->offset = 1;
  190.   menu->pagelen = LINES - 3;
  191.   menu->make_entry = index_make_entry;
  192.   menu->current = ci_first_message ();
  193.  
  194.   helpstr[0] = 0;
  195.   mutt_make_help (buf, sizeof (buf), "Quit  ", MENU_MAIN, OP_QUIT);
  196.   strcat (helpstr, buf);
  197.   mutt_make_help (buf, sizeof (buf), "Del  ", MENU_MAIN, OP_DELETE);
  198.   strcat (helpstr, buf);
  199.   mutt_make_help (buf, sizeof (buf), "Undel  ", MENU_MAIN, OP_UNDELETE);
  200.   strcat (helpstr, buf);
  201.   mutt_make_help (buf, sizeof (buf), "Save  ", MENU_MAIN, OP_SAVE);
  202.   strcat (helpstr, buf);
  203.   mutt_make_help (buf, sizeof (buf), "Mail  ", MENU_MAIN, OP_MAIL);
  204.   strcat (helpstr, buf);
  205.   mutt_make_help (buf, sizeof (buf), "Reply  ", MENU_MAIN, OP_REPLY);
  206.   strcat (helpstr, buf);
  207.   mutt_make_help (buf, sizeof (buf), "Group  ", MENU_MAIN, OP_GROUP_REPLY);
  208.   strcat (helpstr, buf);
  209.   mutt_make_help (buf, sizeof (buf), "Help", MENU_MAIN, OP_HELP);
  210.   strcat (helpstr, buf);
  211.   menu->help = helpstr;
  212.  
  213.   FOREVER
  214.   {
  215.     tag = 0; /* clear the tag-prefix */
  216.  
  217.     menu->max = Context ? Context->vcount : 0;
  218.     oldcount = Context ? Context->msgcount : 0;
  219.  
  220.     if (Context)
  221.     {
  222.       /* check for new mail in the mailbox.  If nonzero, then something has
  223.        * changed about the file (either we got new mail or the file was
  224.        * modified underneath us.)
  225.        */
  226.       index_hint = (Context->vcount) ? CURHDR->index : 0;
  227.  
  228.       if ((i = mx_check_mailbox (Context, &index_hint)) < 0)
  229.       {
  230.     if (!Context->path)
  231.     {
  232.       /* fatal error occurred */
  233.       safe_free ((void **) &Context);
  234.       menu->redraw = REDRAW_FULL;
  235.     }
  236.  
  237.     set_option (OPTSEARCHINVALID);
  238.       }
  239.       else if (i > 0)
  240.       {
  241.     /* take note of the current message */
  242.     if (oldcount)
  243.     {
  244.       if (menu->current < Context->vcount)
  245.         menu->oldcurrent = index_hint;
  246.       else
  247.         oldcount = 0; /* invalid message number! */
  248.     }
  249.  
  250.     /* if the mailbox was reopened, need to rethread from scratch */
  251.     mutt_sort_headers (Context, (i == M_REOPENED));
  252.  
  253.     menu->current = -1;
  254.     if (oldcount)
  255.     {
  256.       int j;
  257.  
  258.       /* restore the current message to the message it was pointing to */
  259.       for (j = 0; j < Context->vcount; j++)
  260.         if (Context->hdrs[Context->v2r[j]]->index == menu->oldcurrent)
  261.         {
  262.           menu->current = j;
  263.           break;
  264.         }
  265.     }
  266.  
  267.     if (menu->current < 0)
  268.       menu->current = ci_first_message ();
  269.  
  270.     /* notify the user of new mail */
  271.     if (i == M_REOPENED)
  272.       mutt_error ("Mailbox was externally modified.  Flags may be wrong.");
  273.     else
  274.       mutt_message ("New mail in this mailbox.");
  275.  
  276.     menu->redraw = REDRAW_FULL;
  277.     menu->max = Context->vcount;
  278.  
  279.     set_option (OPTSEARCHINVALID);
  280.       }
  281.     }
  282.  
  283.     /* check for new mail in the incoming folders */
  284.     oldcount = newcount;
  285.     if ((newcount = mutt_buffy_check ()) != oldcount)
  286.       menu->redraw |= REDRAW_STATUS;
  287.     mutt_buffy_notify ();
  288.  
  289.     mutt_curs_set (0);
  290.  
  291.     if (menu->redraw & REDRAW_FULL)
  292.     {
  293.       menu_redraw_full (menu);
  294.       mutt_show_error ();
  295.     }
  296.  
  297.     if (menu->redraw & REDRAW_STATUS)
  298.     {
  299.       mutt_status_line (buf, sizeof (buf), Status);
  300.       CLEARLINE (option (OPTSTATUSONTOP) ? 0 : LINES-2);
  301.       SETCOLOR (MT_COLOR_STATUS);
  302.       printw ("%-*.*s", COLS, COLS, buf);
  303.       SETCOLOR (MT_COLOR_NORMAL);
  304.       menu->redraw &= ~REDRAW_STATUS;
  305.     }
  306.  
  307.     if (menu->menu == MENU_MAIN)
  308.     {
  309.       if (Context)
  310.       {
  311.     menu_check_recenter (menu);
  312.  
  313.     if (menu->redraw == REDRAW_INDEX)
  314.       menu_redraw_index (menu);
  315.     else if (menu->redraw & (REDRAW_MOTION_RESYNCH |